import { ToolBox } from '../../toolbox/ToolBox';
import KeyEvent from '../android/KeyEvent';
import SvgImage from '../../ui/SvgImage';
import { KeyCodeControlMessage } from '../../controlMessage/KeyCodeControlMessage';
import { ToolBoxButton } from '../../toolbox/ToolBoxButton';
import { ToolBoxElement } from '../../toolbox/ToolBoxElement';
import { ToolBoxCheckbox } from '../../toolbox/ToolBoxCheckbox';
import { StreamClientScrcpy } from '../client/StreamClientScrcpy';
import { BasePlayer } from '../../player/BasePlayer';
import VideoSettings from '../../../app/VideoSettings';
import Size from '../../../app/Size';

const BUTTONS = [
    {
        title: '电源',
        code: KeyEvent.KEYCODE_POWER,
        icon: SvgImage.Icon.POWER,
    },
    {
        title: '放大声音',
        code: KeyEvent.KEYCODE_VOLUME_UP,
        icon: SvgImage.Icon.VOLUME_UP,
    },
    {
        title: '减小声音',
        code: KeyEvent.KEYCODE_VOLUME_DOWN,
        icon: SvgImage.Icon.VOLUME_DOWN,
    },
    {
        title: '返回',
        code: KeyEvent.KEYCODE_BACK,
        icon: SvgImage.Icon.BACK,
    },
    {
        title: '主页',
        code: KeyEvent.KEYCODE_HOME,
        icon: SvgImage.Icon.HOME,
    },
    {
        title: '控制',
        code: KeyEvent.KEYCODE_APP_SWITCH,
        icon: SvgImage.Icon.OVERVIEW,
    },
];

export class GoogToolBox extends ToolBox {
    private static isScreen = true;
    protected constructor(list: ToolBoxElement<any>[]) {
        super(list);
    }

    public static createToolBox(
        udid: string,
        player: BasePlayer,
        client: StreamClientScrcpy,
        moreBox?: HTMLElement,
    ): GoogToolBox {
        const playerName = player.getName();
        const list = BUTTONS.slice();
        const handler = <K extends keyof HTMLElementEventMap, T extends HTMLElement>(
            type: K,
            element: ToolBoxElement<T>,
        ) => {
            if (!element.optional?.code) {
                return;
            }
            const { code } = element.optional;
            const action = type === 'mousedown' ? KeyEvent.ACTION_DOWN : KeyEvent.ACTION_UP;
            const event = new KeyCodeControlMessage(action, code, 0, 0);
            client.sendMessage(event);
        };
        const elements: ToolBoxElement<any>[] = list.map((item) => {
            const button = new ToolBoxButton(item.title, item.icon, {
                code: item.code,
            });
            button.addEventListener('mousedown', handler);
            button.addEventListener('mouseup', handler);
            return button;
        });
        if (player.supportsScreenshot) {
            const screenshot = new ToolBoxButton('Take screenshot', SvgImage.Icon.CAMERA);
            screenshot.addEventListener('click', () => {
                player.createScreenshot(client.getDeviceName());
            });
            elements.push(screenshot);
        }

        const keyboard = new ToolBoxCheckbox(
            '键盘输入',
            SvgImage.Icon.KEYBOARD,
            `capture_keyboard_${udid}_${playerName}`,
        );
        keyboard.addEventListener('click', (_, el) => {
            const element = el.getElement();
            client.setHandleKeyboardEvents(element.checked);
        });
        elements.push(keyboard);

        const changeView = () => {
            GoogToolBox.changeView(player, client);
        };

        const ratio = new ToolBoxButton('全屏/取消全屏', SvgImage.Icon.ASPECT_RATIO);
        ratio.addEventListener('click', () => {
            if (this.isScreen) {
                this.requestFullscreen();
            } else {
                this.exitFullscreen();
            }
            this.isScreen = !this.isScreen;
        });
        elements.push(ratio);

        const fullscreen = new ToolBoxButton('放大', SvgImage.Icon.FULLSCREEN);
        (<HTMLElement>fullscreen.getElement().children[0]).style.width = '18px';
        fullscreen.getElement().id = 'addScreen';
        fullscreen.addEventListener('click', () => {
            client.setExtendScreen(16);
            changeView();
        });
        elements.push(fullscreen);

        const contract = new ToolBoxButton('缩小', SvgImage.Icon.FULLSCREEN_EXIT);
        (<HTMLElement>contract.getElement().children[0]).style.width = '18px';
        contract.addEventListener('click', () => {
            client.setExtendScreen(-16);
            changeView();
        });
        elements.push(contract);

        const magicup = new ToolBoxButton('提升清晰', SvgImage.Icon.MAGIC);
        magicup.addEventListener('click', () => {
            client.setExtendBits(524288);
            changeView();
        });
        elements.push(magicup);

        const magicdump = new ToolBoxButton('降低清晰', SvgImage.Icon.MAGIC);
        magicdump.getElement().style.filter = 'blur(0.65px)';
        magicdump.addEventListener('click', () => {
            client.setExtendBits(-524288);
            changeView();
        });
        elements.push(magicdump);

        const clockwiseup = new ToolBoxButton('加速刷新', SvgImage.Icon.CLOCKWISE);
        clockwiseup.addEventListener('click', () => {
            client.setExtendFps(1);
            changeView();
        });
        elements.push(clockwiseup);

        const clockwisedown = new ToolBoxButton('减速刷新', SvgImage.Icon.CLOCKWISE);
        clockwisedown.getElement().style.filter = 'blur(0.65px)';
        clockwisedown.addEventListener('click', () => {
            client.setExtendFps(-1);
            changeView();
        });
        elements.push(clockwisedown);

        const closeboard = new ToolBoxButton('关闭', SvgImage.Icon.EXIT);
        closeboard.addEventListener('click', () => {
            const btn = document.getElementById('control-button');
            if (btn != null) {
                if (btn.style.display == 'none') {
                    btn.style.display = 'block';
                    btn.style.width = 'auto';
                    btn.style.height = 'auto';
                } else {
                    btn.style.display = 'none';
                    btn.style.width = '0px';
                    btn.style.height = '0px';
                }
            }
        });
        elements.push(closeboard);

        if (moreBox) {
            const displayId = player.getVideoSettings().displayId;
            const id = `show_more_${udid}_${playerName}_${displayId}`;
            const more = new ToolBoxCheckbox('More', SvgImage.Icon.MORE, id);
            more.addEventListener('click', (_, el) => {
                const element = el.getElement();
                moreBox.style.display = element.checked ? 'block' : 'none';
            });
            elements.unshift(more);
        }
        return new GoogToolBox(elements);
    }
    public static changeView(player: BasePlayer, client: StreamClientScrcpy) {
        const bitrate = 4194304 + client.getExtendBits();
        const maxFps = 30 + client.getExtendFps();
        const iFrameInterval = 5;
        const width = window.innerWidth + client.getExtendScreen() + 30;
        const height = window.innerHeight + client.getExtendScreen() + 30;
        if (bitrate < 0 || maxFps < 0 || width < 0 || height < 0) {
            return;
        }
        const bounds = new Size(width, height);
        const current = player.getVideoSettings();
        const { lockedVideoOrientation, sendFrameMeta, displayId, codecOptions, encoderName } = current;
        client.sendNewVideoSetting(
            new VideoSettings({
                bounds,
                bitrate,
                maxFps,
                iFrameInterval,
                lockedVideoOrientation,
                sendFrameMeta,
                displayId,
                codecOptions,
                encoderName,
            }),
        );
        setTimeout(() => {
            const view: any = document.getElementsByClassName('device-view')[0];
            view.style.position = 'absolute';
            view.style.left = 'calc( 50% - ' + view.clientWidth / 2 + 'px )';
            view.style.top = 'calc( 50% - ' + view.clientHeight / 2 + 'px )';
        }, 800);
    }

    private static requestFullscreen() {
        const element: any = document.documentElement;
        if (element.requestFullscreen) {
            element.requestFullscreen();
        } else if (element.mozRequestFullScreen) {
            element.mozRequestFullScreen();
        } else if (element.webkitRequestFullscreen) {
            element.webkitRequestFullscreen();
        } else if (element.msRequestFullscreen) {
            element.msRequestFullscreen();
        }
    }
    private static exitFullscreen() {
        if ((<any>document).exitFullscreen) {
            (<any>document).exitFullscreen();
        } else if ((<any>document).mozCancelFullScreen) {
            (<any>document).mozCancelFullScreen();
        } else if ((<any>document).webkitExitFullscreen) {
            (<any>document).webkitExitFullscreen();
        } else if ((<any>document).msExitFullscreen) {
            (<any>document).msExitFullscreen();
        }
    }
}
